iT邦幫忙

2025 iThome 鐵人賽

DAY 18
1

你是否曾經將心儀的商品加入購物車,卻總是錯過最佳的特價時機?或是需要手動追蹤多個商品的價格,感到既繁瑣又沒效率?

別擔心!本篇文章將帶您一步步利用 n8n 自動化工具,串接 Google Sheets 與 Discord,打造一個專屬於的「商品降價自動通知機器人」。從此以後,你再也不會錯過任何一次降價惹

前置作業

  • 準備 Google 試算表

  • 欄位填上這些

    ProductID ProductName URL LastPrice
  • 表單的內容 ProductID 可以自己設定不會重複的 ID 來表示,剩下的填入自己想追蹤的商品網頁資料

    image 0.png

workflow

步驟一:設定排程觸發

  • 來到儀表板,新增一個流程「Create Workflow」

    image 1.png

  • 初始節點選擇排程「On a schedule」

    image 2.png

  • 選擇每天跑一次

    image 3.png

步驟二:讀取 Google Sheets 資料

  • 下個節點設定去讀取 Google Sheet 的資料,選擇「Get row(s) in sheet」

    image 4.png

  • 憑證的設定方式直接介紹過,這邊就不重複惹,底下選擇自己的工作表

    image 5.png

步驟三:迴圈處理每筆商品

  • 下個節點選擇「Loop Over Items」去拆項執行

    image 6.png

步驟四:抓取網頁價格

  • 把「Replace Me」的節點換成「HTTP Request」

    image 7.png

  • URL 填寫如下來讀取前面的網址

    {
      {
        $json.URL;
      }
    }
    
    • Send Headers 的選項打開,填寫:

      • Name: User-Agent

      • Value: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36

    image 8.png

  • 下個節點選擇「HTML」的「Extract HTML Content」

    image 9.png

  • 接著打開商品網頁,按右鍵的「檢查」觀察價格的元素內容,可以看到「o-prodPrice__price」這個類別

    image 10.png

  • 把相關資料填上去

    • Key:priceText

    • CSS Selector:.o-prodPrice__price

    image 11.png

步驟五:判斷是否降價

  • 下個節點選擇「If」來做判斷

    image 12.png

  • 第一個欄位填寫如下,接著選擇「Numebr」的「is less than」

    {
      {
        Number($json.priceText.replace(/[$,]/g, ""));
      }
    }
    
    • 第二個欄位填寫如下:

      {
        {
          $("Google Sheets").item.json.LastPrice;
        }
      }
      

    image 13.png

步驟六:發送 Discord 通知

  • 接著在「true」路徑的下個節點選擇 Discord 的「Send a message」

    image 14.png

  • 「Connection Type」選擇「Webhook」,憑證的串接在之前的文章有撰寫過,這邊就不重複惹

    image 15.png

  • Message 填入以下內容

    **商品降價通知!** 🚀
    
    **{{ $('Google Sheets').item.json.ProductName }}** 降價囉!
    
    原價: ~${{ $('Google Sheets').item.json.LastPrice }}~
    **新價格: ${{ $('HTML').item.json.priceText }}** 🔥
    
    [點我立刻搶購!]({{ $('Google Sheets').item.json.URL }})
    

步驟七:更新 Google Sheets 價格

  • 下個節點再選擇「Google Sheets」的「Update row in sheet」來更新價格

    image 16.png

  • 在「Column to match on」選擇「ProductID」作為用來判斷的資料行數

    image 17.png

  • LastPrice 的內容填上來更新價格

    {
      {
        Number($("HTML").item.json.priceText.replace(/[$,]/g, ""));
      }
    }
    
    • ProductID 填上

      {
        {
          $("Google Sheets").item.json.ProductID;
        }
      }
      

    image 18.png

  • 再來記得到設定裡面調整時區

    image 19.png

  • 設定為台灣時區

    image 20.png

步驟八:完成迴圈

  • 而當流程跑到「False」的時候也應該要接回「Loop」才會繼續跑下筆資料,所以要把線拉回去連上去

    image 21.png

  • 記得到上方把流程切換為「Active」來啟用,然後點選正下方的「Execute workflow」來試跑看看

    image 22.png

  • Discord 可以看到類似像這樣的訊息,代表成功囉

    image 23.png

  • 最後也附上這個流程的 JSON 內容

    {
      "nodes": [
        {
          "parameters": {
            "rule": {
              "interval": [
                {
                  "triggerAtHour": 8
                }
              ]
            }
          },
          "type": "n8n-nodes-base.scheduleTrigger",
          "typeVersion": 1.2,
          "position": [0, 130],
          "id": "445cc1d9-d9cb-4bc5-bbde-78543bbf4e0b",
          "name": "Schedule Trigger"
        },
        {
          "parameters": {
            "documentId": {
              "__rl": true,
              "value": "YOUR_GOOGLE_SHEET_ID",
              "mode": "list",
              "cachedResultName": "PC24",
              "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_ID/edit?usp=drivesdk"
            },
            "sheetName": {
              "__rl": true,
              "value": "gid=YOUR_GID",
              "mode": "list",
              "cachedResultName": "products",
              "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_ID/edit#gid=YOUR_GID"
            },
            "options": {}
          },
          "type": "n8n-nodes-base.googleSheets",
          "typeVersion": 4.6,
          "position": [220, 130],
          "id": "71925acd-fc55-4fa1-9776-745ae0bdbde0",
          "name": "Google Sheets",
          "credentials": {
            "googleSheetsOAuth2Api": {
              "id": "YOUR_GOOGLE_CREDENTIAL_ID",
              "name": "Google Sheets account"
            }
          }
        },
        {
          "parameters": {
            "options": {}
          },
          "type": "n8n-nodes-base.splitInBatches",
          "typeVersion": 3,
          "position": [440, 130],
          "id": "d0b4932c-250c-4f74-931a-0031199f6dce",
          "name": "Loop Over Items"
        },
        {
          "parameters": {
            "url": "={{ $json.URL }}",
            "sendHeaders": true,
            "headerParameters": {
              "parameters": [
                {
                  "name": "User-Agent",
                  "value": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36"
                }
              ]
            },
            "options": {}
          },
          "type": "n8n-nodes-base.httpRequest",
          "typeVersion": 4.2,
          "position": [660, 140],
          "id": "af7a734c-6ad6-42f0-b89f-bd07a023c85a",
          "name": "HTTP Request"
        },
        {
          "parameters": {
            "operation": "extractHtmlContent",
            "extractionValues": {
              "values": [
                {
                  "key": "priceText",
                  "cssSelector": ".o-prodPrice__price"
                }
              ]
            },
            "options": {}
          },
          "type": "n8n-nodes-base.html",
          "typeVersion": 1.2,
          "position": [880, 140],
          "id": "d570cfec-c06f-442f-854a-39835ea1aedf",
          "name": "HTML"
        },
        {
          "parameters": {
            "conditions": {
              "options": {
                "caseSensitive": true,
                "leftValue": "",
                "typeValidation": "strict",
                "version": 2
              },
              "conditions": [
                {
                  "id": "6fe8d4eb-a606-4307-829b-a7860edde3d2",
                  "leftValue": "={{ Number($json.priceText.replace(/[$,]/g, '')) }}",
                  "rightValue": "={{ $('Google Sheets').item.json.LastPrice }}",
                  "operator": {
                    "type": "number",
                    "operation": "lt"
                  }
                }
              ],
              "combinator": "and"
            },
            "options": {}
          },
          "type": "n8n-nodes-base.if",
          "typeVersion": 2.2,
          "position": [1100, 140],
          "id": "dc921942-f423-4603-a489-e5621bd99165",
          "name": "If"
        },
        {
          "parameters": {
            "authentication": "webhook",
            "content": "=**商品降價通知!** 🚀\n\n**{{ $('Google Sheets').item.json.ProductName }}** 降價囉!\n\n原價: ~${{ $('Google Sheets').item.json.LastPrice }}~\n**新價格: ${{ $('HTML').item.json.priceText }}** 🔥\n\n[點我立刻搶購!]({{ $('Google Sheets').item.json.URL }})",
            "options": {}
          },
          "type": "n8n-nodes-base.discord",
          "typeVersion": 2,
          "position": [1320, 140],
          "id": "6502963f-0b0f-4275-9abe-130898333d3e",
          "name": "Discord",
          "webhookId": "YOUR_DISCORD_WEBHOOK_ID",
          "credentials": {
            "discordWebhookApi": {
              "id": "YOUR_DISCORD_CREDENTIAL_ID",
              "name": "Discord Webhook account"
            }
          }
        },
        {
          "parameters": {
            "operation": "update",
            "documentId": {
              "__rl": true,
              "value": "YOUR_GOOGLE_SHEET_ID",
              "mode": "list",
              "cachedResultName": "PC24",
              "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_ID/edit?usp=drivesdk"
            },
            "sheetName": {
              "__rl": true,
              "value": "gid=YOUR_GID",
              "mode": "list",
              "cachedResultName": "products",
              "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_ID/edit#gid=YOUR_GID"
            },
            "columns": {
              "mappingMode": "defineBelow",
              "value": {
                "LastPrice": "={{ Number($('HTML').item.json.priceText.replace(/[$,]/g, '')) }}",
                "ProductID": "={{ $('Google Sheets').item.json.ProductID }}"
              },
              "matchingColumns": ["ProductID"],
              "schema": [
                {
                  "id": "ProductID",
                  "displayName": "ProductID",
                  "required": false,
                  "defaultMatch": false,
                  "display": true,
                  "type": "string",
                  "canBeUsedToMatch": true,
                  "removed": false
                },
                {
                  "id": "ProductName",
                  "displayName": "ProductName",
                  "required": false,
                  "defaultMatch": false,
                  "display": true,
                  "type": "string",
                  "canBeUsedToMatch": true,
                  "removed": true
                },
                {
                  "id": "URL",
                  "displayName": "URL",
                  "required": false,
                  "defaultMatch": false,
                  "display": true,
                  "type": "string",
                  "canBeUsedToMatch": true,
                  "removed": true
                },
                {
                  "id": "LastPrice",
                  "displayName": "LastPrice",
                  "required": false,
                  "defaultMatch": false,
                  "display": true,
                  "type": "string",
                  "canBeUsedToMatch": true
                },
                {
                  "id": "row_number",
                  "displayName": "row_number",
                  "required": false,
                  "defaultMatch": false,
                  "display": true,
                  "type": "string",
                  "canBeUsedToMatch": true,
                  "readOnly": true,
                  "removed": true
                }
              ],
              "attemptToConvertTypes": false,
              "convertFieldsToString": false
            },
            "options": {}
          },
          "type": "n8n-nodes-base.googleSheets",
          "typeVersion": 4.6,
          "position": [1540, 200],
          "id": "03ef6113-9248-4087-988a-7d17c922da5f",
          "name": "Google Sheets Update",
          "credentials": {
            "googleSheetsOAuth2Api": {
              "id": "YOUR_GOOGLE_CREDENTIAL_ID",
              "name": "Google Sheets account"
            }
          }
        }
      ],
      "connections": {
        "Schedule Trigger": {
          "main": [
            [
              {
                "node": "Google Sheets",
                "type": "main",
                "index": 0
              }
            ]
          ]
        },
        "Google Sheets": {
          "main": [
            [
              {
                "node": "Loop Over Items",
                "type": "main",
                "index": 0
              }
            ]
          ]
        },
        "Loop Over Items": {
          "main": [
            [],
            [
              {
                "node": "HTTP Request",
                "type": "main",
                "index": 0
              }
            ]
          ]
        },
        "HTTP Request": {
          "main": [
            [
              {
                "node": "HTML",
                "type": "main",
                "index": 0
              }
            ]
          ]
        },
        "HTML": {
          "main": [
            [
              {
                "node": "If",
                "type": "main",
                "index": 0
              }
            ]
          ]
        },
        "If": {
          "main": [
            [
              {
                "node": "Discord",
                "type": "main",
                "index": 0
              }
            ],
            [
              {
                "node": "Loop Over Items",
                "type": "main",
                "index": 0
              }
            ]
          ]
        },
        "Discord": {
          "main": [
            [
              {
                "node": "Google Sheets Update",
                "type": "main",
                "index": 0
              }
            ]
          ]
        },
        "Google Sheets Update": {
          "main": [
            [
              {
                "node": "Loop Over Items",
                "type": "main",
                "index": 0
              }
            ]
          ]
        }
      },
      "pinData": {},
      "meta": {
        "templateCredsSetupCompleted": true,
        "instanceId": "YOUR_N8N_INSTANCE_ID"
      }
    }
    

上一篇
[Day17]_Error Trigger
下一篇
[Day19]_股市到價提醒器
系列文
告別重複瑣事: n8n workflow 自動化工作實踐21
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言